package asteroids.model.programs;
import java.util.HashMap;
import java.util.Map;

import asteroids.model.Ship;
import asteroids.model.programs.Expression.SelfLiteral;
import asteroids.model.programs.Expression.VariableLiteral;
import asteroids.model.programs.Statement.*;

/**
* 
* @version 0.3
* @author  Tandan Sunil, Van Deun Luca
*
*/

public class Program {
	public Program(Map<String, Type> globals, Statement statement, HashMap<String, VariableLiteral> variables, SelfLiteral sl) {
		this.statement = (SequenceLiteral) statement;
		this.globals = globals;
		this.variables=variables;
		for(String s: globals.keySet()){
			Type type = globals.get(s);
			VariableLiteral vl =variables.get(s);
			if(vl == null){
				vl = new VariableLiteral(0, 0, s);
			}
			vl.setType(type);
			
		}
		this.sl=sl;
	}
	
	public SelfLiteral getSelfLiteral(){
		return sl;
	}
	private SelfLiteral sl;
	private HashMap<String,VariableLiteral> variables = new HashMap<String,VariableLiteral>();
//	public void changeGlobalVariable(VariableLiteral vl){
//		variables.put(vl.getVariableName(), vl);
//	}
	public VariableLiteral getVariableOf(String variableName){
		return variables.get(variableName);
	}
	
	private SequenceLiteral statement;
	private Map<String,Type>globals;
	public SequenceLiteral getStatement(){
		return statement;
	}
	
	public Map<String,Type> getGlobals(){
		return globals;
	}
	
	private Ship owner;
	public void setOwner(Ship ship){
		if(ship==null)
			throw new IllegalArgumentException("Invalid ship");
		this.owner=ship;
		getSelfLiteral().setEntity(owner);
	}
	public Ship getOwner(){
		return owner;
	}
//	private boolean printed =false;
	
	private boolean includesError;
	public void execute() {
//		if(!printed){
//		printSeqCont(getStatement());
//		printed=true;}
		if(!includesError){
		try{
		getStatement().execute(this);
		}
		catch(Exception e){
			System.out.println("Error occured while executing program. Message:" + e.getMessage());
			includesError = true;
		}
		}
	}
	
	public void executeWithException() {
		getStatement().execute(this);
	}
 
	public void printSeqCont(SequenceLiteral s){
		for(Statement p: s.getStatements()){
			System.out.println("Class: " + p.getClass());
			System.out.println("Line Inside Statement: "+p.getLine());
			System.out.println("Column Inside Statement: "+p.getColumn());
			if(p instanceof SequenceLiteral){
				printSeqCont((SequenceLiteral)p);
			}
			if(p instanceof LoopStatement){
				printSeqCont((SequenceLiteral) ((LoopStatement) p).getBody());
			}
			if(p instanceof IfThenElseLiteral){
				printSeqCont((SequenceLiteral) ((IfThenElseLiteral) p).getThenStatement());
				printSeqCont((SequenceLiteral) ((IfThenElseLiteral) p).getOtherwiseStatement());
			}
				
		}
		
	}
	
	
	

}
